﻿using System.Windows.Controls;

using Aliphant.Datas;
using Aliphant.Interfaces;
using Aliphant.Mvvm.XEvent.Interface;

namespace Aliphant.Mvvm.XEvent.Ioc
{
    public class UIContainer : IUIContainer
    {
        private IDictionary<string, object> _serviceRegistry = new Dictionary<string, object>();
        private IDictionary<string, Func<object>> _serviceFactoryRegistry = new Dictionary<string, Func<object>>();

        #region 依赖注入

        public void Register<TService>() where TService : class, new()
        {
            _serviceRegistry[typeof(TService).Name] = new TService();
            _serviceFactoryRegistry[typeof(TService).Name] = () => new TService();
        }

        public void Register<TService>(string name) where TService : class, new()
        {
            _serviceRegistry[name] = new TService();
            _serviceFactoryRegistry[name] = () => new TService();
        }

        public void Register<TService>(Func<TService> factory) where TService : class
        {
            _serviceRegistry[typeof(TService).Name] = factory;
            _serviceFactoryRegistry[typeof(TService).Name] = factory;
        }

        public void RegisterNavigation<TService>(string name) where TService : class, new()
        {
            _serviceRegistry[name] = new TService();
            _serviceFactoryRegistry[name] = () => new TService();
        }

        public void RegisterRegion<TService>(TService region, string regionName) where TService : class, new()
        {
            _serviceRegistry[regionName] = region;
            _serviceFactoryRegistry[regionName] = () => region;
        }

        public void RegisterFactory<TService>(string name) where TService : class, new()
        {
            _serviceFactoryRegistry[name] = () => new TService();
        }

        #endregion

        public void AddUIModule<TModule>() where TModule : IUIModule, new()
        {
            var module = new TModule();
            module.Register(this);
        }

        public bool Contains<TService>()
        {
            return _serviceRegistry.ContainsKey(typeof(TService).Name);
        }

        public bool ContainsKey(string key)
        {
            return _serviceRegistry.ContainsKey(key);
        }

        public TService Resolve<TService>() where TService : class, new()
        {
            if (_serviceRegistry.ContainsKey(typeof(TService).Name))
            {
                var service = (TService)_serviceRegistry[typeof(TService).Name];
                return service;
            }
            else
            {
                throw new InvalidOperationException($"No service of type {typeof(TService).Name} has been registered.");
            }
        }

        public TService Resolve<TService>(string name) where TService : class, new()
        {
            if (_serviceRegistry.ContainsKey(name))
            {
                var service = (TService)_serviceRegistry[name];
                return service;
            }
            else
            {
                throw new InvalidOperationException($"No service of type {typeof(TService).Name} has been registered.");
            }
        }

        public object Resolve(string name)
        {
            if (_serviceRegistry.ContainsKey(name))
            {
                var service = _serviceRegistry[name];
                return service;
            }
            else
            {
                throw new InvalidOperationException($"No service of {name} has been registered.");
            }
        }

        public object ResolveNew(string name)
        {
            if (_serviceFactoryRegistry.ContainsKey(name))
            {
                var service = _serviceFactoryRegistry[name].Invoke();
                return service;
            }
            else
            {
                throw new InvalidOperationException($"No service of {name} has been registered.");
            }
        }

        public TService ResolveNew<TService>(string name) where TService : class, new()
        {
            if (_serviceFactoryRegistry.ContainsKey(name))
            {
                var service = (TService)_serviceFactoryRegistry[name].Invoke();
                return service;
            }
            else
            {
                throw new InvalidOperationException($"No service of {name} has been registered.");
            }
        }

        public void NavigateTo(string region, string name, NavigateParameter navigateParameter)
        {
            if (string.IsNullOrEmpty(name))
            {
                NavigateToBlank(region);
                return;
            }

            if (!_serviceRegistry.ContainsKey(region) || !_serviceRegistry.ContainsKey(name))
            {
                throw new ArgumentNullException($"Service {region} and {name} are not registered.");
            }

            var regionObj = _serviceRegistry[region];
            var navigationObj = _serviceRegistry[name];

            if (regionObj is ContentControl content)
            {
                content.Content = navigationObj;
                if (navigationObj is UserControl userControl)
                {
                    if (userControl.DataContext is INavigate navigateVM)
                    {
                        navigateVM.OnNavigateTo(navigateParameter);
                    }
                }

            }
        }

        public void NavigateTo(string region, string name)
        {
            NavigateTo(region, name, new NavigateParameter());
        }

        public List<object> GetAllServices()
        {
            return _serviceRegistry.Values.ToList();
        }

        /// <summary>
        /// 导航到空白页
        /// 
        /// 目标区域不存在
        /// </summary>
        /// <param name="region"></param>
        /// <exception cref="ArgumentNullException"></exception>
        private void NavigateToBlank(string region)
        {
            if (!_serviceRegistry.ContainsKey(region))
            {
                throw new ArgumentNullException($"Service {region} is not registered.");
            }
            var regionObj = _serviceRegistry[region];
            if (regionObj is ContentControl content)
            {
                content.Content = null;
            }
        }

        public void CancelRegister(string name)
        {
            if (_serviceRegistry.ContainsKey(name))
            {
                _serviceRegistry.Remove(name);
            }
        }

        private bool disposedValue;

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)
                }

                // TODO: 释放未托管的资源(未托管的对象)并重写终结器
                // TODO: 将大型字段设置为 null
                foreach (var service in _serviceRegistry.Keys)
                {
                    var ins = _serviceRegistry[service];
                    ins = null;
                }
                _serviceRegistry.Clear();
                disposedValue = true;
            }
        }

        // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
        // ~UIContainer()
        // {
        //     // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
        //     Dispose(disposing: false);
        // }

        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }

    }
}
